<script lang="ts" setup name="SwiperPage">
import { ArrowRight, Plus } from '@element-plus/icons-vue'
import { getBannerList, addBanner, updateBanner, deleteBanner } from '@/api/swiper'
import type { Swiper } from '@/types/swiper'
import { ref, reactive, watch } from 'vue'
import type { FormInstance, FormRules, UploadProps, UploadUserFile } from 'element-plus'
import { ElMessage, ElMessageBox } from 'element-plus'
// 将来展示Table要使用
const list = ref<Swiper[]>([])
// 将来展示分页要使用
const total = ref(0)
const swiperQuery = ref({
  page: 1,
  pageSize: 2,
  link: '',
  alt: ''
})

const getBannerListData = async () => {
  const res = await getBannerList(swiperQuery.value)

  list.value = res.data.data.items
  total.value = res.data.data.total
}

getBannerListData()

const clear = () => {
  swiperQuery.value = {
    page: 1,
    pageSize: 2,
    link: '',
    alt: ''
  }

  getBannerListData()
}

// 分页相关
const handleCurrentChange = (page: number) => {
  swiperQuery.value.page = page

  getBannerListData()
}

const handleSizeChange = (pageSize: number) => {
  swiperQuery.value.pageSize = pageSize

  getBannerListData()
}

// 新增 、修改、删除
const dialogVisible = ref(false)
const mode = ref('add')
const formRef = ref<FormInstance>()

// 新增 & 修改的模型
const swiperForm = ref({
  bannerid: '',
  alt: '',
  flag: true,
  img: '',
  link: ''
})

const rules = reactive<FormRules>({
  img: [{ required: true, message: '图片不能为空', trigger: 'blur' }],
  link: [
    { required: true, message: '跳转链接不能为空!', trigger: 'blur' },
    {
      validator: (_, value: string, callback: (value?: string | Error) => void) => {
        const reg =
          /(http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@&#63;^=%&amp;amp;:/~\+#]*[\w\-\@?^=%&amp;/~\+#])?/

        if (reg.test(value)) {
          callback()
        } else {
          callback('跳转地址不合法')
        }
      },
      trigger: 'blur'
    }
  ]
})

// 上传的地址
const uploadUrl = import.meta.env.VITE_APP_BASEURL + 'file/upload' // 图片组件上传是一个独立的功能，没有使用到axios
const fileList = ref<UploadUserFile[]>([])

// 上传前的校验，如果该方法返回了false，则不会发请求，进行文件上传
const beforeAvatarUpload: UploadProps['beforeUpload'] = rawFile => {
  console.log('---beforeAvatarUpload---', rawFile)
  if (swiperForm.value.img) {
    ElMessage.error('你已经有一张图片了，先删掉，再重新上传')
    return false
  }
  if (rawFile.type !== 'image/jpeg' && (rawFile.type as any) !== 'image/png') {
    ElMessage.error('文件必须是JPG 或是 PNG的类型')
    return false
  } else if (rawFile.size / 1024 / 1024 > 2) {
    ElMessage.error('文件大小必须2M以下!')
    return false
  }
  return true
}

// 将来，要预览的图片
// const imageUrl = ref('')
const dialogImageUrl = ref('')
const previewDialogVisible = ref(false)

// 上传成功之后，需要做啥事？
const handleAvatarSuccess: UploadProps['onSuccess'] = (response, uploadFile) => {
  swiperForm.value.img = response.fileUrl

  // 对上传图片那一项进行单独校验
  formRef.value.validateField('img')

  // 给预览图片赋值
  // imageUrl.value = URL.createObjectURL(uploadFile.raw!)
}

const handlePictureCardPreview: UploadProps['onPreview'] = uploadFile => {
  dialogImageUrl.value = uploadFile.url!
  previewDialogVisible.value = true
}

const handleRemove: UploadProps['onRemove'] = (uploadFile, uploadFiles) => {
  swiperForm.value.img = ''
  dialogImageUrl.value = ''
}

const handleExceed: UploadProps['onExceed'] = () => {
  ElMessage.error('最多只允许上传一张图片!')
}

// 修改相关
const edit = (row: Swiper) => {
  mode.value = 'edit'
  // 这种浅拷贝方式，不可以的，会有影响
  // swiperForm.value = row
  // 必须要进行深拷贝
  // 展开是一层深拷贝
  swiperForm.value = { ...row }
  // swiperForm.value = Object.create(row)

  // swiperForm.value = JSON.parse(JSON.stringify(row))

  // 让上传组件显示之前的图片
  fileList.value = [{ url: row.img, name: row.img }]

  dialogVisible.value = true
}

// 提交
const onSubmit = () => {
  // valid 为真，则是校验通过，valid 为 false 则是校验不通过
  formRef.value.validate(async valid => {
    if (!valid) return

    try {
      if (mode.value === 'add') {
        delete swiperForm.value.bannerid

        await addBanner(swiperForm.value)
      } else {
        await updateBanner(swiperForm.value)
      }

      // 关闭对话框
      dialogVisible.value = false

      // 提示
      ElMessage.success(mode.value === 'add' ? '新增成功~' : '修改成功')

      if (mode.value === 'add') {
        // 新增从第一页开始加载
        swiperQuery.value.page = 1
      }
      getBannerListData()
    } catch (error) {}
  })
}

watch(dialogVisible, value => {
  if (!value) {
    mode.value = 'add'

    // 清空表单内容
    swiperForm.value = {
      bannerid: '',
      alt: '',
      flag: true,
      img: '',
      link: ''
    }

    // 清空上传组件中的内容
    fileList.value = []

    // 清空表单校验
    formRef.value.resetFields()
  }
})

// 删除
const del = (bannerid: string) => {
  ElMessageBox.confirm('确定删除吗?', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  })
    .then(async () => {
      await deleteBanner(bannerid)

      // 从第一页重新加载数据
      swiperQuery.value.page = 1
      getBannerListData()
    })
    .catch(() => {})
}
</script>

<template>
  <el-card>
    <el-breadcrumb :separator-icon="ArrowRight">
      <el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
      <el-breadcrumb-item>轮播图管理</el-breadcrumb-item>
      <el-breadcrumb-item>轮播图列表</el-breadcrumb-item>
    </el-breadcrumb>
    <el-form :inline="true" :model="swiperQuery" style="margin-top: 30px" size="large">
      <el-form-item label="跳转链接">
        <el-input v-model="swiperQuery.link" placeholder="请输入跳转链接" />
      </el-form-item>
      <el-form-item label="图片alt">
        <el-input v-model="swiperQuery.alt" placeholder="请输入图片alt" />
      </el-form-item>
      <el-form-item>
        <el-button type="default" @click="clear">清空</el-button>
        <el-button type="primary" @click="getBannerListData">搜索</el-button>
        <el-button type="success" @click="dialogVisible = true">+新增轮播图</el-button>
      </el-form-item>
    </el-form>
  </el-card>
  <el-card style="margin-top: 15px">
    <el-table :data="list">
      <el-table-column label="轮播图图片">
        <template #default="{ row }">
          <el-image
            style="width: 100px; height: 80px"
            :src="row.img"
            :preview-src-list="[row.img]"
            preview-teleported
          >
            <template #error>
              <div
                style="
                  width: 80;
                  height: 80;
                  display: flex;
                  justify-content: center;
                  align-items: center;
                "
              >
                <img style="width: 70px; height: 70px" v-error />
              </div>
            </template>
          </el-image>
        </template>
      </el-table-column>
      <el-table-column label="跳转地址">
        <template #default="{ row }">
          <a :href="row.link" target="_blank">{{ row.link }}</a>
        </template>
      </el-table-column>
      <el-table-column label="轮播图alt" prop="alt" />
      <el-table-column label="启动/禁用">
        <template #default="{ row }">
          <el-switch :model-value="row.flag" />
        </template>
      </el-table-column>
      <el-table-column label="操作">
        <template #default="{ row }">
          <el-button type="primary" @click="edit(row)">修改</el-button>
          <el-button type="danger" @click="del(row.bannerid)">删除</el-button>
        </template>
      </el-table-column>
    </el-table>
    <el-pagination
      v-model:current-page="swiperQuery.page"
      v-model:page-size="swiperQuery.pageSize"
      :page-sizes="[1, 2, 5, 10]"
      layout="total, sizes, prev, pager, next, jumper"
      :total="total"
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
    />
  </el-card>
  <el-dialog
    v-model="dialogVisible"
    :title="mode === 'add' ? '新增轮播图' : '修改轮播图'"
    width="60%"
  >
    <el-form
      ref="formRef"
      :model="swiperForm"
      :rules="rules"
      label-width="120px"
      class="demo-ruleForm"
      size="large"
    >
      <el-form-item label="轮播图图片" prop="img">
        <!-- 
          action：上传地址
          v-model:file-list 上传之后的图片渲染（上传、删除它会相应的变化）
          list-type：图片显示的方式
          以下是钩子：
            before-upload：上传前的钩子
            on-success：上传成功了
            on-preview：预览上传完的头像
            on-remove：干掉
        -->
        <el-upload
          :action="uploadUrl"
          v-model:file-list="fileList"
          list-type="picture-card"
          :limit="1"
          :before-upload="beforeAvatarUpload"
          :on-success="handleAvatarSuccess"
          :on-preview="handlePictureCardPreview"
          :on-remove="handleRemove"
          :on-exceed="handleExceed"
        >
          <el-icon><Plus /></el-icon>
        </el-upload>
        <!-- 预览图片的弹框 -->
        <el-dialog v-model="previewDialogVisible">
          <img w-full :src="dialogImageUrl" alt="Preview Image" />
        </el-dialog>
      </el-form-item>
      <el-form-item label="跳转链接" prop="link">
        <el-input v-model="swiperForm.link" />
      </el-form-item>
      <el-form-item label="alt说明">
        <el-input v-model="swiperForm.alt" />
      </el-form-item>
      <el-form-item label="启动/禁用">
        <el-switch v-model="swiperForm.flag" />
      </el-form-item>
    </el-form>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="dialogVisible = false">取消</el-button>
        <el-button type="primary" @click="onSubmit"> 确定 </el-button>
      </span>
    </template>
  </el-dialog>
</template>

<style scoped></style>
